using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;


namespace RunAllTestsInSolutionTask
{
    public class CSharpProjectParser : BaseProjectParser
    {

        public CSharpProjectParser(string projectFileName)
            :base(projectFileName)
        { }

        public override bool IsTestProject()
        {
            var ans = from projectType in _projectXml.Descendants()
                      where (projectType.Name.LocalName == "ProjectTypeGuids")
                      select projectType;
            foreach (var type in ans)
            {
                if (type.Value.Contains(TEST_TYPE_GUID))
                    return true;

            }
            return false;
        }

        public override string GetOutputFile(string configuration)
        {
            if (string.IsNullOrEmpty(configuration))
            {
                configuration = "debug";
            }
            var projectXml = XDocument.Load(_projectFileName);
            string outputDll = GetoutputFileName(projectXml, configuration);

            return Path.Combine(Path.GetDirectoryName(_projectFileName), outputDll);

        }



        private static string GetoutputFileName(XDocument projectXml, string configuration)
        {
            string assemblyName = GetAssemblyFileName(projectXml);
            string outputPath = GetOutputPath(projectXml, configuration);
            string extension = GetExtension(projectXml);

            return Path.Combine(outputPath, assemblyName) + extension;
        }

        private static string GetAssemblyFileName(XDocument projectXml)
        {
            var assemblyName = (from projectType in projectXml.Descendants()
                                where (projectType.Name.LocalName == "AssemblyName")
                                select projectType).Single();
            return assemblyName.Value;
        }

        private static string GetOutputPath(XDocument projectXml, string configuration)
        {
            var propertiesElement = GetConfigurationPropertyGroup(projectXml, configuration);
            XElement outputPath = GetOutputPathElement(propertiesElement);
            return outputPath.Value;
        }

        private static XElement GetConfigurationPropertyGroup(XDocument projectXml,string configuration)
        {
            var  propertiesGroups = from x in projectXml.Descendants()
                                   where x.Name.LocalName == "PropertyGroup"
                                   select x;


            var propertyGroup = (from x in propertiesGroups
                                where ( (x.Attribute("Condition") != null) &&
                                  (x.Attribute("Condition").Value.Contains(configuration)) )
                                select x);

            return propertyGroup.First();
        }

        private static XElement GetOutputPathElement(XElement configurationElemnt)
        {
            var outputPath = (from projectType in configurationElemnt.Descendants()
                              where (projectType.Name.LocalName == "OutputPath")
                              select projectType).First();
            return outputPath;
        }
        
        private static string GetExtension(XDocument projectXml)
        {
            if (IsClassLibrary(projectXml))
                return ".dll";
            else
                return ".exe";
        }

        private static bool IsClassLibrary(XDocument projectXml)
        {
            var outputType = (from projectType in projectXml.Descendants()
                              where (projectType.Name.LocalName == "OutputType")
                              select projectType).First();
            if (outputType.Value == "Exe")
                return false;
            return true;
        }
    }
}